﻿//#define USE_DUNGEONBUDDY_DLL

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using CommonBehaviors.Actions;
using Styx;
using Styx.Common.Helpers;
using Styx.CommonBot;
using Styx.CommonBot.Frames;
using Styx.Helpers;
using Styx.Patchables;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
#if USE_DUNGEONBUDDY_DLL
using Bots.DungeonBuddyDll;
using Bots.DungeonBuddyDll.Profiles;
using Bots.DungeonBuddyDll.Attributes;
using Bots.DungeonBuddyDll.Helpers;

namespace Bots.DungeonBuddyDll.Dungeon_Scripts.Mists_of_Pandaria
#else
    using Bots.DungeonBuddy.Profiles;
    using Bots.DungeonBuddy.Attributes;
    using Bots.DungeonBuddy.Helpers;
namespace Bots.DungeonBuddy.Dungeon_Scripts.Mists_of_Pandaria
#endif
{
    internal class BrewingStorm : Dungeon
    {
        #region Overrides of Dungeon

        public override uint DungeonId
        {
            get { return 517; }
        }

        public override void RemoveTargetsFilter(List<WoWObject> units)
        {
            units.RemoveAll(
                ret =>
                {
                    var unit = ret.ToUnit();
                    if (unit != null)
                    {
                        // ignore these while they're scaling cliffs
                        if ((unit.Entry == ViletongueDecimatorId || unit.Entry == ViletongueSkirmisherId || unit.Entry == ViletongueWarriorId) && unit.TransportGuid > 0)
                            return true;
                    }
                    return false;
                });
        }

        public override void IncludeTargetsFilter(List<WoWObject> incomingunits, HashSet<WoWObject> outgoingunits)
        {
            foreach (var obj in incomingunits)
            {
                var unit = obj as WoWUnit;
                if (unit != null)
                {
                    if (unit.Combat && unit.CurrentTargetGuid != 0 && unit.CurrentTarget.Entry == BrewmasterBlancheId)
                        outgoingunits.Add(unit);
                }
            }
        }

        public override void WeighTargetsFilter(List<Targeting.TargetPriority> units)
        {
            foreach (var priority in units)
            {
                var unit = priority.Object as WoWUnit;
                if (unit != null) { }
            }
        }

        #endregion

        private const uint BrewkegId = 58916;
        private const uint BrewmasterBlancheId = 58740;
        private const uint ViletongueSkirmisherId = 58738;
        private const uint ViletongueDecimatorId = 59632;
        private const uint ViletongueWarriorId = 58737;

        private static LocalPlayer Me
        {
            get { return StyxWoW.Me; }
        }

        [EncounterHandler(0)]
        public Composite RootEncounter()
        {
            const uint healingCircleId = 114663;
            WoWDynamicObject healingCircle = null;

            return new PrioritySelector(
                ctx => healingCircle = ObjectManager.GetObjectsOfType<WoWDynamicObject>().FirstOrDefault(u => u.Entry == healingCircleId),
                new Decorator(
                    ctx => healingCircle != null && Me.HealthPercent < 80 && Me.Location.Distance(healingCircle.Location) > 4,
                    new Action(ctx => Navigator.GetRunStatusFromMoveResult(Navigator.MoveTo(healingCircle.Location)))),
                new Decorator(ctx => ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex == 0, StageOneEncounter()),
                new Decorator(ctx => ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex == 0, StageOneEncounter()));
        }

        [EncounterHandler(58740, "Brewmaster Blanche", Mode = CallBehaviorMode.Proximity)]
        public Composite BrewmasterBlancheEncounter()
        {
            return
                new PrioritySelector(
                    new Decorator<WoWUnit>(unit => unit.CanGossip && Me.RaidMembers.All(r => r.IsAlive && r.HealthPercent > 90), ScriptHelpers.CreateTalkToNpc(58740)));
        }

        public Composite StageOneEncounter()
        {
            const uint davesIndustrialLightandMagicBunnyId = 38821;

            AddAvoidObject(ctx => true, 5, u => u.Entry == davesIndustrialLightandMagicBunnyId && u.ToUnit().HasAura("Lightning Channel"));


            var encounterLoc = new WoWPoint(2249.904, -1132.496, 485.9289);
            WoWUnit kegOnFire = null;

            return new PrioritySelector(
                ctx =>
                {
                    kegOnFire =
                        ObjectManager.GetObjectsOfType<WoWUnit>().Where(u => u.Entry == BrewkegId && u.HasAura("On Fire")).OrderBy(u => u.DistanceSqr).FirstOrDefault();

                    return ctx;
                },
                new Decorator(
                    ctx => kegOnFire != null && Me.HealthPercent >= 80 && Targeting.Instance.IsEmpty(),
                    new PrioritySelector(
                        new Decorator(ctx => !kegOnFire.WithinInteractRange, new Action(ctx => Navigator.MoveTo(kegOnFire.Location))),
                        new Decorator(ctx => kegOnFire.WithinInteractRange, new Action(ctx => kegOnFire.Interact())))),
                // stay close to encounter.
                new Decorator(ctx => Targeting.Instance.IsEmpty() && Me.Location.Distance(encounterLoc) > 30, new Action(ctx => Navigator.MoveTo(encounterLoc))),
                // don't move to next boss before eveny is over.
                new Decorator(ctx => Me.IsTank() && Targeting.Instance.IsEmpty(), new ActionAlwaysSucceed()));
        }

        public Composite StageTwoEncounter()
        {
            var escortMoveLoc = new WoWPoint(2179.667, -1016.134, 450.7713);
            return new PrioritySelector(
                ctx => ObjectManager.GetObjectsOfType<WoWUnit>().FirstOrDefault(u => u.Entry == BrewmasterBlancheId),

                new Decorator<WoWUnit>(unit => Me.IsTank() && Targeting.Instance.IsEmpty() && unit.Distance > 20,
                    new Helpers.Action<WoWUnit>(unit => Navigator.GetRunStatusFromMoveResult(Navigator.MoveTo(unit.Location)))),

                // move to escort to location if blanche is nowhere to be found.
                new Decorator(ctx => Me.IsTank() && ctx == null, new Action(ctx => ScriptHelpers.MoveTankTo(escortMoveLoc))));
        }

        // todo. finish behavior.
        [EncounterHandler(58739, "Borokhula the Destroyer")]
        public Composite BorokhulaTheDestroyerEncounter()
        {
            const int swampSmashId = 115013;
            const int earthShatteringId = 122142;

            return new PrioritySelector();
        }
    }
}